第 18 天我們已經把 skill.md 找到了,也知道 OpenClaw 會把它做成 snapshot。
但故事還沒結束。
因為真正難的不是「有沒有 skill」,而是:
換句話說,skill.md 被讀到只是開始。
真正重要的是它被處理成什麼。
第 19 天我想看的就是這件事:
skill 從定義到執行,OpenClaw 怎麼處理它?
skillsSnapshot?.prompt 為什麼重要?skillUsagePaths 在做什麼?skill 的處理可以想成四段:
skill.md
這裡最容易誤會的是第三段和第四段。
很多人會以為 skill 是某種「執行插件」。
其實不是。
它更像是:
讓模型知道自己現在該用什麼方式工作的一份上下文。
OpenClaw 不是把 skill 當腳本跑,而是把 skill 當成運行規範的一部分。
先看第 18 天的 snapshot 怎麼被一路帶進 turn。
📄 原始碼:
src/agents/agent-command.ts:1400-1428
const skillFilter = resolveEffectiveAgentSkillFilter(cfg, sessionAgentId);
const currentSkillsSnapshot = sessionEntry?.skillsSnapshot;
const [{ getRemoteSkillEligibility, resolveReusableWorkspaceSkillSnapshot }, { canExecRequestNode }] = await Promise.all([
loadSkillsRuntime(),
loadExecDefaultsRuntime()
]);
const skillSnapshotState = resolveReusableWorkspaceSkillSnapshot({
skillFilter,
currentSkillsSnapshot,
workspaceDir,
agentDir,
agentId: sessionAgentId,
canExecRequestNode,
getRemoteSkillEligibility
});
const skillsSnapshot = skillSnapshotState.snapshot;
這裡的重點是:
接著看它怎麼進到 developer instructions。
📄 原始碼:
extensions/codex/src/app-server/thread-lifecycle.ts:3062-3062
function buildDeveloperInstructions(params) {
return [
"Running inside OpenClaw. Use dynamic tools for messaging, cron, sessions, media, gateway, and nodes when available.",
"Use Codex native `spawn_agent` for Codex subagents. Use OpenClaw `sessions_spawn` only for OpenClaw or ACP delegation; if it is not already loaded, search for `sessions_spawn` in the `openclaw` dynamic tool namespace before calling it.",
"Preserve channel/session context. Visible channel replies: use `message`, do not describe would-reply.",
renderCodexRuntimePromptOverlay(params),
params.extraSystemPrompt,
params.skillsSnapshot?.prompt
].filter((section) => typeof section === "string" && section.trim()).join("\\n\\n");
}
這段非常直接。
skillsSnapshot?.prompt 被併到 developer instructions,代表 skill 不是外圍資料,而是模型看得見的指令背景。
再看 skill 相關資訊怎麼進到 runtime hooks。
📄 原始碼:
src/agents/agent-tools.ts:1131-1151
const hookContext = {
agentId,
...(options?.config ? { config: options.config } : {}),
cwd: codingRoot,
workspaceDir: workspaceRoot,
...(options?.skillsSnapshot ? { skillsSnapshot: options.skillsSnapshot } : {}),
...(options?.skillUsagePaths ? { skillUsagePaths: options.skillUsagePaths } : {}),
...(sandboxRoot && allowWorkspaceWrites
? { sandbox: { root: sandboxRoot, bridge: sandboxFsBridge! } }
: {}),
sessionKey: options?.sessionKey,
sessionId: options?.sessionId,
runId: options?.runId,
approvalReviewerDeviceId: options?.approvalReviewerDeviceId,
channelId: options?.hookChannelId ?? options?.currentChannelId,
...(turnSourceChannel ? { turnSourceChannel } : {}),
...(turnSourceTo ? { turnSourceTo } : {}),
...(options?.agentAccountId ? { turnSourceAccountId: options.agentAccountId } : {}),
...(options?.currentThreadTs ? { turnSourceThreadId: options.currentThreadTs } : {}),
...(options?.trace ? { trace: options.trace } : {}),
loopDetection: resolveToolLoopDetectionConfig({ cfg: options?.config, agentId }),
onToolOutcome: options?.onToolOutcome,
allocateToolOutcomeOrdinal: options?.allocateToolOutcomeOrdinal,
};
這裡的 skillsSnapshot 和 skillUsagePaths 很重要。
它代表 skill 不只是 prompt,還可能影響:
也就是說,skill 不是只在模型腦袋裡飄一段字。
它有可能還會被 runtime 追蹤、被工具 hook 看見。
skill.md 是「定義」,skillsSnapshot 是「實例」這個分工很像 class 和 instance。
skill.md 是原始定義skillsSnapshot 是當下 turn 可用的實例狀態這樣的好處是:
如果你只是把 skill 放在提示文字裡,它可能只是「建議」。
但當它被放進 developer instructions、hook context、usage paths 之後,它就會變成更實際的工作邊界:
這就是 OpenClaw 比較成熟的地方。
它不是只讓模型「看到」,而是讓整個 runtime 都知道。
skillUsagePaths 值得看因為它代表 skill 不只是文字說明,還可能涉及實際資源路徑。
對長流程系統來說,這很重要:
如果沒有這一層,你很難知道 skill 到底有沒有真的被使用。
你可以把它想成:
skill.md -> snapshot -> prompt -> runtime context -> model behavior -> tool usage
這條鏈的任何一段出問題,都會讓 skill 看起來像「沒生效」。
所以第 19 天的重點不是某個單一函式,而是整條處理管線。
plugin 比較像外掛入口,skill 比較像內建知識與工作方式。
plugin 主要解決「接哪裡」。
skill 主要解決「怎麼想、怎麼做」。
OpenClaw 把這兩個分得很清楚,整個系統就比較不會亂。
但這種設計很像成熟系統應該有的樣子。
它不追求「看起來簡單」,它追求「行為穩定」。
skill.md 是定義,不是執行本體params.skillsSnapshot?.prompt 會直接進 developer instructionshookContext 會帶上 skillsSnapshot 和 skillUsagePaths
前兩天把 cron 和 skill 這兩個特殊 turn / 能力層都補完之後,下一篇就可以把前 20 天整個收斂起來。
前 20 天收斂,把 OpenClaw 畫成一張地圖